#include "command.h"
string get_name(string args, string type);

string get_db_name(string args)
{
    return get_name(args, "database");
}
string get_table_name(string args)
{
    return get_name(args, "table");
}
string get_insert_name(string args)
{
    return get_name(args, "into");
}

string get_name(string args, string type)
{
    // 查找type后面的名字
    size_t pos = args.find(type);
    if (pos == string::npos)
        return "";
    // 跳到type最后一个字母
    pos += type.size();
    while (pos < args.size() && isspace(args[pos]))
        pos++; // 跳过空白
    // 找下一个空白
    size_t end = pos;
    while (end < args.size() && !isspace(args[end]))
        end++;
    return args.substr(pos, end - pos);
}
/**
 * 向指定列中插入值
 *
 * @param column_ 一个列对象，包含列的名称、类型和值集合
 * @param name_val 一个包含列名和值的键值对
 *
 * 此函数首先检查传入的列名是否与键值对中的列名相匹配如果匹配，则根据列的数据类型，
 * 将值插入到列的值集合中支持的数据类型包括int、string、float和double对于不支持的数据类型，
 * 函数将抛出错误
 */
void my_insert(column &column_, std::pair<string, string> name_val)
{
    /*匹配名称*/
    if (column_.name == name_val.first)
    {

        /*根据数据类型插入值*/
        if (column_.type == "int")
        {
            // 将字符串转换为int类型
            int value = atoi(name_val.second.c_str());
            column_.values.push_back(value);
        }
        else if (column_.type == "string")
        {
        string value = name_val.second;
        if (value.size() >= 2 && value.front() == '\'' && value.back() == '\'') {
            value = value.substr(1, value.size() - 2);
        }
        column_.values.push_back(value);
        }   
        else if (column_.type == "float")
        {
            // 将字符串转换为float类型
            float value = atof(name_val.second.c_str());
            column_.values.push_back(value);
        }
        else if (column_.type == "double")
        {
            // 将字符串转换为double类型
            double value = atof(name_val.second.c_str());
            column_.values.push_back(value);
        }
        else
        {
            // 如果遇到未知的数据类型，抛出错误
            error("insert table error,no such column type %s\n", column_.type.c_str());
        }
    }
}

void create_db(string args)
{
    string token = get_db_name(args);
    // 创建一个新的数据库对象
    db db_;
    // 设置数据库对象的名称
    db_.name = token;
    // 初始化数据库对象的表列表为空
    db_.tables = {};
    database.push_back(db_);
}
/**
 * 删除数据库
 *
 * 该函数根据提供的参数获取数据库名称，并从全局数据库列表中删除该数据库
 * 如果数据库不存在，则输出错误信息
 *
 * @param args 包含数据库名称的字符串参数
 */
void drop_db(string args)
{
    // 从参数中获取数据库名称
    string token = get_db_name(args);

    // 遍历全局数据库列表，寻找匹配的数据库名称
    for (int i = 0; i < static_cast<int>(database.size()); i++)
    {
        // 如果找到匹配的数据库，从列表中擦除并返回
        if (database[i].name == token)
        {
            database.erase(database.begin() + i);
            return;
        }
    }

    // 如果未找到匹配的数据库，输出错误信息
    error("drop database error,no such database %s\n", token.c_str());
}

/**
 * 使用数据库
 *
 * 该函数根据提供的参数获取数据库名称，并设置当前正在使用的数据库
 * 如果数据库不存在，则输出错误信息
 *
 * @param args 包含数据库名称的字符串参数
 * @param current_db 引用类型，用于存储当前正在使用的数据库
 */
db *use_db(string args, bool &db_process)
{
    // 遍历全局数据库列表，寻找匹配的数据库名称
    for (auto &db_ : database)
    {
        // 如果找到匹配的数据库，将其设置为当前正在使用的数据库并返回
        if (db_.name == args)
        {
            db_process = false;
            return &db_;
        }
    }
    // 如果未找到匹配的数据库，输出错误信息
    error("use database error,no such database %s\n", args.c_str());
    return NULL;
}
void create_table(string args, db *current_db)
{
    /*语法create table xxx (col_type col_name1, col_type col_name2, … );*/
    string table_name = get_table_name(args);
    args = args.substr(table_name.size() + 6);
    /*create_table_helper函数实现在flex（create_table.l）
    声明在command_uitls.h中 */
    map<string, string> column_type_name = create_table_helper(args);
    table t;
    t.name = table_name;
    for (auto i : column_type_name)
    {
        column c;
        c.type = i.second;
        c.name = i.first;
        t.columns.push_back(c);
    }
    current_db->tables.push_back(t);
}
/**
 * 删除数据库中的表
 *
 * 该函数根据提供的参数获取表名，并在当前数据库中查找并删除该表如果表不存在，
 * 则输出错误信息这个函数演示了如何在内存中的数据库表示中删除一个表
 *
 * @param args 包含待删除表名的字符串参数
 * @param current_db 当前操作的数据库对象
 */
void drop_table(string args, db *current_db)
{
    // 从参数中提取表名
    string table_name = get_table_name(args);

    // 遍历当前数据库中的所有表
    for (int i = 0; i < (int)current_db->tables.size(); i++)
    {
        // 如果找到待删除的表
        if (current_db->tables[i].name == table_name)
        {
            // 从数据库的表列表中移除该表
            current_db->tables.erase(current_db->tables.begin() + i);
            // 表删除成功，函数结束
            return;
        }
    }

    // 如果没有找到待删除的表，输出错误信息
    error("drop table error,no such table %s\n", table_name.c_str());
    return;
}
/**
 * @brief 显示指定数据库表的结构信息
 *
 * @param args 包含目标表名的字符串参数
 * @param current_db 当前数据库对象，包含多个数据表
 *
 * 该函数会解析输入参数中的表名，在数据库对象中查找匹配的数据表，
 * 并输出该表的名称及所有列的类型和名称信息
 */
void info_table(string args, db current_db)
{
    // 从输入参数中提取目标表名
    string table_name = get_table_name(args);
    bool find_table = false;
    // 遍历数据库中的所有数据表
    for (auto table_ : current_db.tables)
    {
        // 查找与目标表名匹配的数据表
        if (table_.name == table_name)
        {

            find_table = true;
            // 输出表名信息
            printf("table name:%s\n", table_.name.c_str());

            // 输出列标题
            printf("columns:\n");

            // 遍历并输出所有列的类型和名称
            for (auto column_ : table_.columns)
            {
                printf("%s %s\n", column_.type.c_str(), column_.name.c_str());
            }
        }
    }
    if (!find_table)
    {
        // 如果没有找到匹配的表，输出错误信息
        error("info table error,no such table %s\n", table_name.c_str());
    }
}

/*insert into xxx set col_name1=col_value1,col_name2=col_value2,…*/
/**
 * 向数据库中插入数据
 *
 * @param args 插入操作的参数字符串，包含表名和插入的值
 * @param current_db 当前操作的数据库对象
 *
 * 此函数解析插入操作的参数，匹配数据库中的表，并根据表结构插入相应的值
 * 它通过调用辅助函数来解析参数字符串，并根据数据类型将值插入到正确的列中
 */

void insert_table(string args, db *current_db)
{
    // 获取插入操作的表名
    string name = get_insert_name(args);
    bool table_find = false;
    // 遍历数据库中的所有表，寻找匹配的表名
    for (auto &table_ : current_db->tables)
    {
        if (table_.name == name)
        {
            table_find = true;

            // 构造解析掩码，用于提取插入操作中的值
            string mask = "into " + name + " set ";
            string name_value_sp = args.substr(mask.size());
            string name_value;
            for (char c : name_value_sp)
            {
                if (c != ' ')
                    name_value += c;
            }
            /*在command_util声明下面的函数，实现在insert_table.l中 */
            map<string, string> column_name_val = insert_table_helper(name_value);

            /*遍历插入操作中的值，并插入到对应的列中 */
            for (const auto &name_val : column_name_val)
            {
                for (auto &column_ : table_.columns)
                {
                    my_insert(column_, name_val);
                }
            }
        }
    }
    if (!table_find)
    {
        error("insert table error,no such table %s\n", name.c_str());
    }
}
// void select_table(string args,db *current_db){
//     char name_buf[2000];
//     char table_buf[200];
//     /*args为col_name1,col_name2, … from xxx [where condition] [order by col_name] [asc/desc]
//     %s 会解析col_name1,col_name2, …*/
//     sscanf(args.c_str(),"%s from %s",name_buf,table_buf);
//     vector<string> names;
//     name_str2vector(name_buf,names);
//     string table_name=table_buf;
//     string head_mask=(string)name_buf+(string)" from "+table_name;
//     string where_oredr_condition=remove_str_from_head(args,)

// }
// void delete_table(string args,db *current_db){

// }
